using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Win32;
using System.Runtime.InteropServices;

namespace Waymex.Security
{
    internal class Licencing
    {

        //try and call the external dll, this is a standard dll protected by Installshield
        //for try/buy licencing
        //[DllImport("Waymex.Licence.dll", SetLastError = true)]
        //unsafe internal static extern bool GetLicence();

        /// <summary>
        /// Date based Licencing method
        /// </summary>
        /// <param name="productName">Installshields product code</param>
        /// <param name="version">Installshields product version</param>
        /// <param name="expiryDays">Days until licence expires</param>
        /// <returns></returns>
        internal static LicenceStatus GetLicenceStatus(string productName, string version, double expiryDays)
        {
            LicenceStatus licStatus = LicenceStatus.licenceNonExistent;

            try
            {
                //get registry key created by installshield
                //RegistryKey licenseKey = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + installShieldProductCode);
				RegistryKey licenseKey = Registry.LocalMachine.OpenSubKey("Software\\Waymex\\" + productName + "\\" + version);

                //ensure registry key exists
                if (licenseKey != null)
                {

                    // Passed the first test, which is the existence of the
                    // Registry key itself. Now obtain the stored value
                    // associated with our app's install date.
                    // get the encrypted value
                    string date = (string)licenseKey.GetValue("");

                    //check status of date
                    if (date != null)
                    {

                        //decrypt the date int YYYMMDD format
                        date = DecryptDate(date);

                        DateTime installDate = new DateTime(
                            Convert.ToInt32(date.Substring(0, 4)),
                            Convert.ToInt32(date.Substring(4, 2)),
                            Convert.ToInt32(date.Substring(6, 2))
                            );

                        //assume date good so calculate expiry date
                        DateTime expDate = installDate.AddDays(expiryDays);

                        //see if trial period is valid i.e. after current date but within 'expiryDays'
                        if (expDate >= DateTime.Now.Date && expDate <= DateTime.Now.AddDays(expiryDays).Date)
                        {
                            //all ok
                            licStatus = LicenceStatus.licenceValid;
                        }
                        else
                        {
                            //good licence but expired
                            licStatus = LicenceStatus.licenceNotValid;
                        }
                    }
                }
            }
            catch //horendous but this is an exceptional situation
            {
                licStatus = LicenceStatus.licenceNonExistent;
            }
            return licStatus;
        }

        //**************************************************************************************************
        //used in the DecryptDate function below SEE Waymex.Licensing.dll for matching encryption
        //see document c11.pdf 'Simple Encryption for details'
        const int kSTART = 0;
        const int kINCREMENT = 1;
        const int len = 10;
        //substitution table for chars 1 2 3 4 5 6 7 8 9 0 respectively as used in Waymex.Licence.dll
        static int[] substitutions = { 7, 1, 5, 2, 6, 8, 4, 3, 0, 9 };
        //**************************************************************************************************

        private static string DecryptDate(string encryptedDate)
        {
            // This decrypt function is paired with the encrypt used in the Waymex.Licencing.dll

            char[] chars = encryptedDate.ToCharArray();
            char[] date = new char[chars.Length];

            int k = kSTART;

            //create the reverse lookup table
            int[] rtable = new int[substitutions.Length];
            int index = 0;
            foreach (int f in substitutions)
            {
                rtable[f] = index;
                index++;
            }

            for (int i = 0; i < chars.Length; i++)
            {
                //find index of value
                int t = rtable[chars[i] - 48];
                t -= k; //t = t - k
                while (t < 0)
                {
                    t += len; //t=t+len
                }
                date[i]= (char)(t + 48);

                k += kINCREMENT;
            }

            return new string(date);
        }
    }
}
